package pluginMain;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Iterator;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.entity.*;

import skill.SkillManager;

public class Lore extends JavaPlugin implements Listener {
	public final String PLUGIN_NAME = "RemiliaNetwork Lore";
	public static Logger CONSOLE_LOGGER;
	private EffectsParser de;

	public static LivingEntity getDamager(EntityDamageByEntityEvent e) {
		if (e.getDamager() instanceof Projectile) {
			Projectile p = ((Projectile) e.getDamager());
			if (p.getShooter() instanceof HumanEntity)
				return (LivingEntity) (p.getShooter());
			else
				return (LivingEntity) p.getShooter();
		} else if (e.getDamager() instanceof ThrownPotion) {
			ThrownPotion t = ((ThrownPotion) e.getDamager());
			if (t.getShooter() instanceof HumanEntity)
				return (LivingEntity) (t.getShooter());
			else
				return (LivingEntity) t.getShooter();
		} else if (e.getDamager() instanceof LivingEntity) {
			return (LivingEntity) e.getDamager();
		} else {
			return null;
		}
	}

	public static LivingEntity getEntity(EntityDamageByEntityEvent e) {
		if (e.getEntity() instanceof Projectile) {
			Projectile p = ((Projectile) e.getEntity());
			if (p.getShooter() instanceof HumanEntity)
				return (LivingEntity) (p.getShooter());
			else
				return (LivingEntity) p.getShooter();
		} else if (e.getEntity() instanceof ThrownPotion) {
			ThrownPotion t = ((ThrownPotion) e.getEntity());
			if (t.getShooter() instanceof HumanEntity)
				return (LivingEntity) (t.getShooter());
			else
				return (LivingEntity) t.getShooter();
		} else if (e.getEntity() instanceof LivingEntity) {
			return (LivingEntity) e.getEntity();
		} else {
			return null;
		}
	}

	public static String r2(double n) {
		return (new DecimalFormat("#.00")).format(n);
	}

	public static void LOGCONSOLE(String msg) {
		CONSOLE_LOGGER.info(msg);
	}

	public static SkillManager sm;
	public static Lore instance;
	public static EventListener el;
	public static EffectsLib ef;
	public Configer pluginFolder;

	public static BAKAScoreboard instanceSB;
	public static final String SCORE_DPS = "&2输出值";

	@Override
	public void onEnable() {
		instance = this;
		CONSOLE_LOGGER = instance.getLogger();
		instanceSB = (BAKAScoreboard) getServer().getPluginManager().getPlugin("BAKAScoreboard");
		Configer.ReleaseFileIfNotExist(this, "example.txt");

		RegisteredServiceProvider<SkillManager> service = getServer().getServicesManager()
				.getRegistration(SkillManager.class);
		if (service == null) {
			LOGCONSOLE("Require SP plugin first");
			setEnabled(false);
			return;
		}
		sm = service.getProvider();
		if (sm == null) {
			LOGCONSOLE("Can't get instance of SkillManager in SP");
			setEnabled(false);
			return;
		}

		LOGCONSOLE("Registing Event driver...");

		getServer().getPluginManager().registerEvents(this, this);

		LOGCONSOLE("Done.");

		LOGCONSOLE("Loading Lore Effects...");
		ef = new EffectsLib();
		LOGCONSOLE("Done.");
		LOGCONSOLE(PLUGIN_NAME + " has been started.");
	}

	@Override
	public void onDisable() {
		LOGCONSOLE(PLUGIN_NAME + " has been disabled.");
	}

	@Override
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
		if (args[0] != "reload") {
			sender.sendMessage("Bad command request");
			return false;
		}
		if (sender instanceof Player) {
			if (!sender.hasPermission("lore.reload")) {
				sender.sendMessage("Permission Deny. Command Fail.");
				return false;
			}
		}

		ef = new EffectsLib();
		LOGCONSOLE("Lore effect library reloaded!");
		sender.sendMessage("Reload Complete!");
		return true;
	}

	@EventHandler
	public void onEntityDamage(EntityDamageByEntityEvent e) {
		// clear manager first
		//LOGCONSOLE("Event Pass");
		de = new EffectsParser();
		de.clear();
		// if damager holding a weapon
		if (e.getDamager() instanceof LivingEntity) {
			LivingEntity source = getDamager(e);
			ItemStack item = source.getEquipment().getItemInHand();
			addSupportLoresFromStack(item, true);
		}
		// if target is living entity
		if (e.getEntity() instanceof LivingEntity) {
			LivingEntity entity = getEntity(e);
			for (ItemStack s : entity.getEquipment().getArmorContents()) {
				addSupportLoresFromStack(s, false);
			}
		}
		// Final, pass event to manager and get final Result
		
		de.doEffects(e);
		de.clear();
		
		if (e.getDamager() instanceof Player){
			Lore.instanceSB.showInfo((Player) e.getDamager(), Lore.SCORE_DPS, (int) de.getFinalDamage());
			//((Player)e.getDamager()).sendMessage("DPS :" + ChatColor.RED + Lore.r2(de.getFinalDamage()));
		}
	}

	public void addSupportLoresFromStack(ItemStack item, boolean effectApply) {
		try {
			if (!item.hasItemMeta())
				return;
			if (!item.getItemMeta().hasLore())
				return;
			List<String> lores = new ArrayList<>();
			lores.addAll(item.getItemMeta().getLore());

			Iterator<String> k;

			k = lores.iterator();
			while (k.hasNext()) {
				String value = k.next();
				Matcher m = Pattern.compile("\\[Lore\\].*?\\[(.+?)\\].*?\\[(\\d+)-(\\d+)\\].*?").matcher(value);
				if (m.find()) {
					de.addBaseEffect(m.group(1), Integer.parseInt(m.group(2)), Integer.parseInt(m.group(3)));
					k.remove();
				}
			}
			if (effectApply) {
				k = lores.iterator();
				while (k.hasNext()) {
					String value = k.next();
					Matcher m = Pattern.compile("\\[Lore\\].*?\\[(.+)\\].*?\\[([^-]+)\\].*?").matcher(value);
					if (m.find()) {
						de.addEffect(m.group(1), m.group(2));
						k.remove();
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
